package com.leadcore.lockscreen.wallpaper;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import static android.os.ParcelFileDescriptor.MODE_CREATE;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;;

public class LockscreenWallpaperManager {

    private static final String LOCKSCREEN = "lockscreen";
    private static final String LOCKSCREEN_WALLPAPER = "lockscreen";
    private static final String INTERNAL_SDCARD = System.getenv("EXTERNAL_STORAGE");
    private static final String TAG = "LockscreenWallpaperManager";

    public static void setResource(Context context, int resid) throws IOException {
            Resources resources = context.getResources();
            /* Set the wallpaper to the default values */
            ParcelFileDescriptor fd = getFiledescriptor();
            if (fd != null) {
                FileOutputStream fos = null;
                try {
                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                    setWallpaper(resources.openRawResource(resid), fos);
                } finally {
                    if (fos != null) {
                        fos.close();
                    }
                }
            }
    }

    public static void setBitMap(Bitmap b) throws IOException {
            ParcelFileDescriptor fd = getFiledescriptor();
            if (fd == null) {
                return;
            }
            FileOutputStream fos = null;
            try {
                fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                b.compress(Bitmap.CompressFormat.PNG, 90, fos);
            } finally {
                if (fos != null) {
                    fos.close();
                }
            }
    }

    public static void setStream(InputStream data) throws IOException {
            ParcelFileDescriptor fd = getFiledescriptor();
            if (fd == null) {
                return;
            }
            FileOutputStream fos = null;
            try {
                fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                setWallpaper(data, fos);
            } finally {
                if (fos != null) {
                    fos.close();
                }
            }
    }

    private static void setWallpaper(InputStream data, FileOutputStream fos) throws IOException {
        byte[] buffer = new byte[32768];
        int amt;
        while ((amt=data.read(buffer)) > 0) {
            fos.write(buffer, 0, amt);
        }
    }

    static ParcelFileDescriptor getFiledescriptor() {
        String dirs = INTERNAL_SDCARD + "/" + LOCKSCREEN;
        try {
            File dir = new File(dirs);
            if (!dir.exists()) {
                dir.mkdir();
                            FileUtils.setPermissions(
                                dir.getPath(),
                                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                                -1, -1);
                }
            File file = new File(dir, LOCKSCREEN_WALLPAPER);
                ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
                        MODE_CREATE|MODE_READ_WRITE);
            return fd;
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static Drawable getDrawable(Context context) {
        Bitmap bm = getCurrentWallpaperLocked(context);
        if (bm != null) {
            Drawable dr = new BitmapDrawable(context.getResources(), bm);
            dr.setDither(false);
            return dr;
        }
        return null;
    }

    public static Bitmap getBitmap(Context context) {
        Bitmap mWallpaper = null;
        try {
            mWallpaper = getCurrentWallpaperLocked(context);
        } catch (OutOfMemoryError e) {
            Log.w(TAG, "No memory load current wallpaper", e);
        }
        return mWallpaper;
    }

    public static void clear() {
        String filePath = INTERNAL_SDCARD + "/" + LOCKSCREEN + "/" + LOCKSCREEN_WALLPAPER;
        File file = new File(filePath);
        if(file.exists()) {
            file.delete();
        }
    }
    private static Bitmap getCurrentWallpaperLocked(Context context) {
        File f = new File(INTERNAL_SDCARD + "/" + LOCKSCREEN, LOCKSCREEN_WALLPAPER);
        if (!f.exists()) {
            return null;
        }
        ParcelFileDescriptor fd = null;
        try {
            fd = ParcelFileDescriptor.open(f, MODE_READ_ONLY);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "open wallpaper file error: " + e);
        }
        if (fd != null) {
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                Bitmap bm = BitmapFactory.decodeFileDescriptor(
                        fd.getFileDescriptor(), null, options);
                return generateBitmap(context, bm);
            } catch (OutOfMemoryError e) {
                Log.w(TAG, "Can't decode file", e);
            } finally {
                try {
                    fd.close();
                } catch (IOException e) {
                    // Ignore
                }
            }
        }
        return null;
    }

    private static Bitmap generateBitmap(Context context, Bitmap bm) {
        if(bm == null) {
            return null;
        }
        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metrics);
        bm.setDensity(metrics.noncompatDensityDpi);
        int width = metrics.widthPixels;
        int height = metrics.heightPixels;

        Log.d(TAG, "generateBitmap width is " + width + " height is " + height);
        if (width <= 0 || height <= 0
                || (bm.getWidth() == width && bm.getHeight() == height)) {
            return bm;
        }
        try {
            Bitmap newbm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            newbm.setDensity(metrics.noncompatDensityDpi);

            Canvas c = new Canvas(newbm);
            Rect targetRect = new Rect();
            targetRect.right = bm.getWidth();
            targetRect.bottom = bm.getHeight();

            int deltaw = width - targetRect.right;
            int deltah = height - targetRect.bottom;

            if (deltaw > 0 || deltah > 0) {
                // We need to scale up so it covers the entire area.
                float scale;
                if (deltaw > deltah) {
                    scale = width / (float)targetRect.right;
                } else {
                    scale = height / (float)targetRect.bottom;
                }
                targetRect.right = (int)(targetRect.right*scale);
                targetRect.bottom = (int)(targetRect.bottom*scale);
                deltaw = width - targetRect.right;
                deltah = height - targetRect.bottom;
            }

            targetRect.offset(deltaw/2, deltah/2);

            Paint paint = new Paint();
            paint.setFilterBitmap(true);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
            c.drawBitmap(bm, null, targetRect, paint);

            bm.recycle();
            c.setBitmap(null);
            return newbm;
        } catch (OutOfMemoryError e) {
            Log.w(TAG, "Can't generate default bitmap", e);
            return bm;
        }
    }
}
